package com.samehope.ar.socket.handler;

import com.samehope.ar.entity.Device;
import com.samehope.ar.entity.SysUser;
import com.samehope.ar.service.IDeviceService;
import com.samehope.ar.util.JwtTokenUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.net.URLDecoder;

/**
 * @Description: 授权请求处理
 * @Author: ZhangLuo
 * @Email: 1946430@qq.com
 */
@Slf4j
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    public static final AttributeKey<String> TOKEN = AttributeKey.valueOf("token");
    public static final AttributeKey<SysUser> USER = AttributeKey.valueOf("user");
    public static final AttributeKey<Device> DEVICE = AttributeKey.valueOf("device");

    /**
     * 校验token是否有效
     */
    private JwtTokenUtil jwtTokenUtil;

    /**
     * 设备接口
     */
    private IDeviceService deviceService;

    public HttpRequestHandler(JwtTokenUtil jwtTokenUtil, IDeviceService deviceService) {
        this.jwtTokenUtil = jwtTokenUtil;
        this.deviceService = deviceService;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
        // 获取webSocket连接的地址
        String url = request.uri();

        if(-1 != url.indexOf("/ws")) {
            // 分隔url 获取参数
            String[] splits = url.split("\\?");
            if(splits.length >= 2) {

                // 请求的参数部分
                String paramStr = URLDecoder.decode(splits[1], "UTF-8");

                // 分隔请求参数
                String[] params = paramStr.split("&");

                // 识别参数
                String deviceMac = null;
                String token = null;
                for (String param : params) {
                    String[] keyAndValue = param.split("=");
                    if (keyAndValue.length != 2) {
                        ctx.close();
                        return;
                    }
                    String value = URLDecoder.decode(keyAndValue[1], "UTF-8");
                    if ("deviceMac".equals(keyAndValue[0])) {
                        deviceMac = value;
                    } else if ("token".equals(keyAndValue[0])) {
                        token = value;
                    }
                    log.info("value : {}", value);
                }

                // 参数校验逻辑
                if (StringUtils.isBlank(deviceMac) && StringUtils.isBlank(token)) {
                    log.error("没有携带参数mac & token, 请求被终止: {}", url);
                    ctx.close();
                    return;
                }

                if (StringUtils.isNotBlank(token) && jwtTokenUtil.isTokenExpired(token)) {
                    log.error("非法或无效的 token: {}", token);
                    ctx.close();
                    return;
                }

                Device device = deviceService.findByDeviceMac(deviceMac);
                if (StringUtils.isNotBlank(deviceMac) && device == null) {
                    log.error("错误或不存在的设备mac编号: {}", deviceMac);
                    ctx.close();
                    return;
                }

                // token有效, 升级握手, 绑定token和用户信息
                if (StringUtils.isNotBlank(token)) {

                    // 获取用户信息
                    SysUser sysUser = jwtTokenUtil.getSysUser(token);
                    if (sysUser == null) {
                        log.warn("非法的TOKEN, 无法获取用户对象, token: {}", token);
                        ctx.close();
                        return;
                    } else {
                        ctx.channel().attr(TOKEN).set(token);
                        ctx.channel().attr(USER).set(sysUser);
                        log.info("用户: {} 连接webSocket成功!", sysUser.getMobile());
                    }
                    // 传递到下一个handler：升级握手
                } else {
                    // mac 有效, 升级握手, 绑定 设备信息
                    ctx.channel().attr(DEVICE).set(device);
                }

                // 升级握手
                request.setUri("/ws");
                ctx.fireChannelRead(request.retain());
            } else {
                log.warn("非法请求: {}", url);
                ctx.close();
                return;
            }
        } else {
            log.error("not socket");
            ctx.close();
        }
    }

}
